package com.imyuanma.qingyun.common.config.security;

import com.imyuanma.qingyun.common.model.response.Result;
import com.imyuanma.qingyun.common.util.ClientInfoUtil;
import com.imyuanma.qingyun.common.util.JsonUtil;
import com.imyuanma.qingyun.common.util.WebUtil;
import com.imyuanma.qingyun.interfaces.ums.model.LoginSuccess;
import com.imyuanma.qingyun.interfaces.ums.model.TerminalDTO;
import com.imyuanma.qingyun.interfaces.ums.service.IUmsPermissionsOutService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 登录成功后处理器
 *
 * @author wangjy
 * @date 2022/07/09 20:53:51
 */
@Component
public class DefaultLoginSuccessHandler implements AuthenticationSuccessHandler {
    private static final Logger logger = LoggerFactory.getLogger(DefaultLoginSuccessHandler.class);

    /**
     * 权限服务
     */
    @Autowired
    private IUmsPermissionsOutService permissionsOutService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        logger.info("[登录成功后处理器] 登录验证成功,用户={},URI={},权限信息={}", request.getParameter("account"), request.getRequestURI(), JsonUtil.toJson(authentication));
        if (!(authentication.getPrincipal() instanceof DefaultUserDetails)) {
            throw new ServletException("未知的UserDetails实现");
        }
        DefaultUserDetails userDetails = (DefaultUserDetails) authentication.getPrincipal();
        // 登录成功后持久化会话信息
        String token = permissionsOutService.createSessionAfterLoginCheckSuccess(userDetails.getLoginUserDTO(), this.buildTerminalDTO(request));
        logger.info("[登录成功后处理器] 成功创建会话token={}", token);
        // 将令牌更新到认证对象中, 在上下文资源库用来写入令牌
        userDetails.tokenAfterLoginSuccess(token);

        // 写cookie
        Cookie cookie = new Cookie(SecurityConstants.TOKEN_KEY, userDetails.getToken());
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
        logger.info("[登录成功后处理器] 写入cookie凭证token={}到响应头", userDetails.getToken());

        // 登录结果
        LoginSuccess loginSuccess = new LoginSuccess(userDetails.getUsername(), token, request.getParameter("redirectTo"));
        // 写入响应
        Result<LoginSuccess> result = Result.success(loginSuccess);
        WebUtil.write2Response(response, result);
        logger.info("[登录成功后处理器] 写入登录请求返回结果={}", result);
    }

    /**
     * 客户端信息
     *
     * @param request
     * @return
     */
    private TerminalDTO buildTerminalDTO(HttpServletRequest request) {
        String ip = ClientInfoUtil.getClientIpAddr(request);
        TerminalDTO terminalDTO = new TerminalDTO();
        terminalDTO.setDeviceAddr(ip);
        terminalDTO.setDeviceType(1);
        terminalDTO.setDeviceVersion("");
        terminalDTO.setClientIp(ip);
        return terminalDTO;
    }
}
